/**
 * 
 * @author Matan Mizrahi,Chen weissman
 * Introduction to computer science, assingment5
 * Date:2.1.2011
 *
 * The Cosine class, in which implement the Expression Interface
 * represents the Cosine Expression (i.e., cose(a), where a is an expression)
 * A cosine expression can be evaluated, derived and return its last operation symbol.
 *
 */

public class Cosine implements Expression {
	//*********************************Fields************************************//

    private Expression exp;

    //*********************************Constructors******************************//

    /**
     * Constructor that creates a cosine expression
     *
     * @param exp the expression
     * @throws RuntimeException for null input expression
     */
	//**********************************Methods*******************************//

    public Cosine(Expression exp) {
        if (exp == null) {
            throw new RuntimeException("Cosine constructor got a null argument.");
        }
        this.exp = exp;
    }

    /**
     * Returns the last operation symbol of Cosine Expression
     *
     * @return String "cos" that represents the last operation
     */
    public String getLastOperationSymbol() {
        return "cos";
    }

    /**
     * Evaluates the cosine expression
     *
     * @return double that represents the evaluation of the cosine expression
     * @throws Exception  in case the assignment is null or if the variable is not assigned to a value
     */
    public double evaluate(Assignment assign) throws Exception {
        return Math.cos(exp.evaluate(assign));
    }

    /**
     * Derives the cosine expression by a variable.
     *
     * @param var the variable to derive by
     * @return the derived expression by param var
     * @throws RuntimeException for a null var
     */
    public Expression derivative(char varName) {
        return new Multiplication(new Multiplication(new Constant(-1), new Sine(exp)),exp.derivative(varName));
    }
	/**
	 * Replicating the invoking object.
	 * 
	 * @return a replicate of this object. The returned object has
	 * to be a new object (with a different address than this
	 * object), but equivalent to the this object under the 
	 * application of the {@code equals(Object other)} method.
	 */
	public Expression replicate(){
		return new Cosine(this.exp);
	}
    /**
     * Compares this cosine expression to the specified object.
     * The result is true if and only if the argument is not null, the argument is instance of cosine expression and the sub-expressions are equals.
     *
     * @param other The object to compare this expression against
     * @return true if the given object represents an expression equivalent to this expression, false otherwise
     */
    public boolean equals(Object other) {
        return ((other instanceof Cosine) &&
                (exp.equals(((Cosine) other).exp)));
    }

    /**
     * Returns a string representing the cosine expression.
     *
     * @return String that represents the cosine expression
     */
    public String toString() {
        return getLastOperationSymbol() + "(" + exp.toString() + ")";
    }

}
